module phy88E1512_init(
    input   clk,
    input   rst, 
    output  mdc,//1MHZ
    // inout               mdio,  
	output  mdi,
	input   mdo,
	output  mdio_ctr,

    input   [4:0]   phy_id,
    output  reg     phy_init_done,
    input   done_ini,
	 output reg [1:0] phy_speed
);





reg [7:0] init_state;
reg [7:0] nxt_state;
  
reg [15:0] send_data;
reg vaild_in;
reg wr;                 // 0:write 1:read
reg [4:0] reg_id;
wire vaild_out;
wire [15:0] rd_data;
reg [15:0] data_reg;
reg [31:0] u_delay;


always @ (posedge clk or negedge rst)
begin
	if(!rst)
	begin
		init_state <= 8'd0;
		nxt_state  <= 8'd0;
		reg_id <= 0;
		send_data <= 0;
		wr <= 1'b0;
		phy_init_done <= 1'b0;
		u_delay <= 32'd0;
		vaild_in <= 1'b0;
	end
	else case(init_state)
			8'd0:
			begin
				if(done_ini)
				begin
					init_state <= 8'd1;
				end
				else
				begin
					init_state <= 8'd0;
				end
				reg_id <= 0;
				send_data <= 0;
				wr <= 1'b0;
				u_delay <= 32'd0;
				phy_init_done <= 1'b0;
				vaild_in <= 1'b0;
			end
			8'd1:begin init_state <= 8'd50;nxt_state  <= 8'd2;reg_id <= 5'd22; send_data <= 16'h0000;wr <= 1'b0;end//配置PHY页地址 page 0
			8'd2:begin init_state <= 8'd50;nxt_state  <= 8'd3;reg_id <= 5'd03; send_data <= 16'h0000;wr <= 1'b1;end//读page0 - reg3
			8'd3:
			begin
				if(rd_data[15:10] ==6'b000011 && rd_data[9:4] ==6'b011101)
				begin
					init_state <= 8'd4;
				end
				else
				begin
					init_state <= 8'd0;
				end
			end
			8'd4: begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd5; reg_id <= 5'd22; send_data <= 16'h00ff;wr <= 1'b0;end
			8'd5: begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd6; reg_id <= 5'd17; send_data <= 16'h214B;wr <= 1'b0;end
			8'd6: begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd7; reg_id <= 5'd16; send_data <= 16'h2144;wr <= 1'b0;end
			8'd7: begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd8; reg_id <= 5'd17; send_data <= 16'h0C28;wr <= 1'b0;end	
			8'd8: begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd9; reg_id <= 5'd16; send_data <= 16'h2146;wr <= 1'b0;end
			8'd9: begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd10;reg_id <= 5'd17; send_data <= 16'hB233;wr <= 1'b0;end	
			8'd10:begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd11;reg_id <= 5'd16; send_data <= 16'h214D;wr <= 1'b0;end
			8'd11:begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd12;reg_id <= 5'd17; send_data <= 16'hCC0C;wr <= 1'b0;end	
			8'd12:begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd13;reg_id <= 5'd16; send_data <= 16'h2159;wr <= 1'b0;end
			8'd13:begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd14;reg_id <= 5'd22; send_data <= 16'h0000;wr <= 1'b0;end	
			8'd14:begin init_state <= 8'd50;nxt_state  <= 8'd15;reg_id <= 5'd22; send_data <= 16'd18;  wr <= 1'b0;end//Page 18
			8'd15:begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd16;reg_id <= 5'd20; send_data <= 16'h0000;wr <= 1'b1;end//read
			8'd16:begin init_state <= init_state + 1'b1; end
			// begin
			// 	data_reg <= (rd_data & 16'hfff8) + 16'h0001;
			// 	init_state <= 8'd17;
			// end//
			// 8'd17:begin init_state <= 8'd50;nxt_state  <= 8'd18;reg_id <= 5'd20; send_data <= data_reg;wr <= 1'b0;end
			8'd17:begin init_state <= 8'd50;nxt_state  <= 8'd18;reg_id <= 5'd20; send_data <= 16'h0201;wr <= 1'b0;end
			8'd18://delay some time
			begin
				if(u_delay == 32'hffff_f)
				begin
					u_delay <= 32'd0;
					init_state <= 8'd19;
				end
				else
				begin
					u_delay <= u_delay + 32'd1;
					init_state <= 8'd18;				
				end
			end	
			8'd19:begin init_state <= init_state + 1'b1; end //begin init_state <= 8'd50;nxt_state  <= 8'd20;reg_id <= 5'd20;wr <= 1'b1;end//read
			8'd20:
			begin
				data_reg <= rd_data | 16'h8000;
				init_state <= 8'd21;
			end//phy reset
			8'd21:begin init_state <= 8'd50;nxt_state  <= 8'd22;reg_id <= 5'd20; send_data <= data_reg;wr <= 1'b0;end
			
			/*KeyStone EMAC does not support 1000M half-duplex.
        
            Configure the PHY register 9_0.8 to 0, which means 1000Mbps half duplex will 
        
            not be advertised to the remote side which connects to the copper media of 
        
            this PHY. This step will make sure that the copper side of PHY will not 
        
            negotiate 1000Mbps half duplex capability with remote media.*/
            
			8'd22:begin init_state <= 8'd50;nxt_state  <= 8'd23;reg_id <= 5'd22; send_data <= 16'h0000;wr <= 1'b0;end//Page 0 
			8'd23:begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd24;reg_id <= 5'd9;  send_data <= 16'h0000;wr <= 1'b1;end//read
			8'd24:begin init_state <= init_state + 1'b1; end // 
			// begin
			// 	data_reg <= rd_data & 16'b1111_1110_1111_1111;
			// 	init_state <= 8'd25;
			// end//Full-Duplex
			8'd25:begin init_state <= 8'd50;nxt_state  <= 8'd26;reg_id <= 5'd9;  send_data <= 16'h0200;wr <= 1'b0;end //16'b0000_0010_0000_0000
            /*Configure the PHY register 21_2 "default MAC interface speed" to 10, which 
        
            means 1000Mbps. This step will make sure when the Fiber/SGMII side of PHY status 
        
            switch between link up and link down, it will not issue 1000M half duplex request 
        
            to CPSGMII module of the DSP. (Note, this configuration will NEVER force the 
        
            link rate to 100Mbps, the link rate depends on the final negotiation result) */
			8'd26:begin init_state <= 8'd50;nxt_state  <= 8'd27;reg_id <= 5'd22; send_data <= 16'h0002;wr <= 1'b0;end//Page 2 
			8'd27:begin init_state <= init_state + 1'b1; end // begin init_state <= 8'd50;nxt_state  <= 8'd28;reg_id <= 5'd21; send_data <= 16'h0002;wr <= 1'b1;end//read
			8'd28:begin init_state <= init_state + 1'b1; end // 
			// begin
			// 	data_reg <= rd_data | 16'b0010_0000_0000_0000;
			// 	init_state <= 8'd29;		
			// end
			8'd29:begin init_state <= 8'd50;nxt_state  <= 8'd30;reg_id <= 5'd21;  send_data <= 16'h1076;wr <= 1'b0;end//16'b0001_0000_0111_0110
			
			/* software reset to make configuration take effect*/
			8'd30:begin init_state <= 8'd50;nxt_state  <= 8'd31;reg_id <= 5'd22;  send_data <= 16'h0000;wr <= 1'b0;end//Page 0 
			8'd31:begin init_state <= 8'd50;nxt_state  <= 8'd32;reg_id <= 5'd0;   send_data <= 16'h0000;wr <= 1'b1;end//read
			8'd32:
			begin
				data_reg <= rd_data | 16'b1000_0000_0000_0000;
				init_state <= 8'd33;		
			end//PHY Reset
			8'd33:begin init_state <= 8'd50;nxt_state  <= 8'd34;reg_id <= 5'd0;  send_data <= data_reg;wr <= 1'b0;end
			
			8'd34://Delay for PHY Reset
            begin
                if(u_delay == 32'hfff)
                begin
                    u_delay <= 32'd0;
                    init_state <= 8'd35 ;
                end
                else
                begin
                    u_delay <= u_delay + 32'd1;
                    init_state <= init_state;                
                end
            end
            8'd35:begin init_state <= 8'd50;nxt_state  <= 8'd36;reg_id <= 5'd22;  send_data <= 16'h0000;wr <= 1'b0;end//Page 0 
            8'd36:begin init_state <= 8'd50;nxt_state  <= 8'd37;reg_id <= 5'd17;  send_data <= 16'h0000;wr <= 1'b1;end//
			8'd37:
			begin
			     if(rd_data[10] == 1'b1)//link_up
			     begin
			         init_state <= 8'd38;        
			     end
			     else
			     begin
			         init_state <= 8'd36;   
			     end
			     phy_speed <= rd_data[15:14];
			end		
			8'd38:
			begin
			    phy_init_done <= 1'b1;
			    init_state <= 8'd38;
			end
			8'd50:
			begin
			     if(vaild_out == 1'b1)
			     begin
			         vaild_in <= 1'b0;
			         init_state <= 8'd51;
			     end
			     else
			     begin
			         vaild_in <= 1'b1;
			         init_state <= 8'd50;
			     end
			end
			8'd51:
			begin
                if(u_delay == 32'hfff)
                begin
                    u_delay <= 32'd0;
                    init_state <= nxt_state;
                end
                else
                begin
                    u_delay <= u_delay + 32'd1;
                    init_state <= init_state;                
                end
            end

			default:
				begin
				init_state <= 8'd0;
				nxt_state  <= 8'd0;
				reg_id <= 0;
				send_data <= 0;
				wr <= 1'b0;
				phy_init_done <= 1'b0;
				vaild_in <= 1'b0;
				end
	endcase
end

phy_mdio phy_mdio(
    .clk(clk),
    .rst(rst),          // Active low
    
    .mdc(mdc),     // Max 12M
    .mdi(mdi),
    .mdo(mdo),
    .mdio_ctr(mdio_ctr),    // 1: mdo valid  0: mdi valid

    .phy_id(5'b0_0000),
    .reg_id(reg_id),

    .wr(wr),
    .send_data(send_data),
    .send_data_vld(vaild_in),
    .recv_data(rd_data),
    .wr_done(vaild_out)
);

// ila_0 ila_0 (
// 	.clk(clk), // input wire clk
// 	.probe0(mdc), // input wire [0:0]  probe0  
// 	.probe1(1'b0), // input wire [0:0]  probe1 
// 	.probe2(nxt_state), // input wire [0:0]  probe2 
// 	.probe3(init_state), // input wire [7:0]  probe3 
// 	.probe4(reg_id), // input wire [4:0]  probe4 
// 	.probe5(send_data), // input wire [15:0]  probe5 
// 	.probe6(vaild_in), // input wire [0:0]  probe6 
// 	.probe7(wr), // input wire [0:0]  probe7 
// 	.probe8(vaild_out), // input wire [0:0]  probe8 
// 	.probe9(rd_data) // input wire [15:0]  probe9
// );	


endmodule
